package wechat.pay;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.weixin4j.Configuration;
import org.weixin4j.User;
import org.weixin4j.WXPayUtil;
import org.weixin4j.Weixin;
import org.weixin4j.WeixinException;
import org.weixin4j.http.OAuth2Token;
import org.weixin4j.pay.UnifiedOrder;
import org.weixin4j.pay.UnifiedOrderResult;
import org.weixin4j.util.MapUtil;
import org.weixin4j.web.AdvancedUtil;
import org.weixin4j.WXPayConstants.SignType;

import com.common.CommonUtil;
import com.common.WebUtils;
import com.filter.BaseController;

import beans.sys.SYSCodeBean;
import beans.user.order;
import beans.user.recommendgold;
import beans.user.user;
import beans.user.xh;
import service.SpringContextUtil;
import service.sys.SYSCodeServiceImpl;
import service.user.OrderServiceImpl;
import service.user.RecommendgoldServiceImpl;
import service.user.WXUserServiceImpl;
import service.user.XHServiceImpl;

@Controller
@RequestMapping("/wxpay")
public class OpenPayController extends BaseController{

	@Resource
	private OrderServiceImpl<order> orderServiceImpl;
	@Resource
	private WXUserServiceImpl<user> wxUserServiceImpl;

	@RequestMapping("/payindex")
	public String payindex() throws Exception {
		String code = getReq().getParameter("code");
		if(null != code && !"".equals(code)){
			System.out.println(code);
			//根据code换取openId
			OAuth2Token oa = AdvancedUtil.getOauth2AccessToken(Configuration.getOAuthAppId(), Configuration.getOAuthSecret(),code);
			if(!"".equals(oa) && null != oa){
				user temUser = wxUserServiceImpl.queryById(oa.getOpenid());
				if(temUser==null) {
					return "wechat/home/noright";
				}
				else
					getReq().getSession().setAttribute("wxuser", temUser);
				return "wechat/pay/index";
			}else{//登录失败
				return "wechat/home/noright";
			}
		}
		else {
			user user = (user) getReq().getSession().getAttribute("wxuser");
			if(user==null) {
				return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid="+Configuration.getOAuthAppId()+"&redirect_uri=http%3a%2f%2f2.zydkj.net.cn%2fwx%2findex&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
			}

			List<order> orderList = orderServiceImpl.getPayInfo();
			for(order o :orderList) {
				if(!CommonUtil.isNullObject(o.getNickname())) {
					o.setNickname(o.getNickname().substring(0, o.getNickname().length()-1)+"*");
				}
			}
			getReq().getSession().setAttribute("orderList", orderList);

			return "wechat/pay/index";
		}
	}

	@RequestMapping("/paydetail")
	public String paydetail(String id) throws Exception {
		BigDecimal money = new BigDecimal(19.90);  
		BigDecimal bignum2 = new BigDecimal("100");
		if(id.equals("6")) money = BigDecimal.valueOf(19.90);//单位元
		else if(id.equals("2"))money= BigDecimal.valueOf(38);//单位元
		else if(id.equals("8"))money= BigDecimal.valueOf(58);//单位元
		BigDecimal dOrderMoney = money.multiply(bignum2);

		String payid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
		String noceStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
		String appid = Configuration.getOAuthAppId();
		String mcid = Configuration.getMCId();
		String notifyurl = Configuration.getNotify();
		String ip = WebUtils.getIpAddr(getReq());
		//String ip = "218.91.211.214";

		user u = (user)getReq().getSession().getAttribute("wxuser");

		//调用微信统一支付接口
		Map<String, String> reqData = new HashMap<>();
		reqData.put("appid", appid);
		reqData.put("body", "会员开通");
		reqData.put("mch_id", mcid);
		reqData.put("nonce_str", noceStr);
		reqData.put("notify_url", notifyurl);
		reqData.put("openid", u.getOpenid());
		reqData.put("out_trade_no", payid);
		reqData.put("spbill_create_ip", ip);
		reqData.put("total_fee", String.valueOf(dOrderMoney.intValue()));//元转成分
		reqData.put("trade_type", "JSAPI");
		String sign = WXPayUtil.generateSignature(reqData, Configuration.getMCKey(), SignType.MD5);
		reqData.put("sign", sign);

		Weixin wx = new Weixin();
		UnifiedOrder unifiedorder = new UnifiedOrder();
		unifiedorder.setAppid(appid);
		unifiedorder.setBody("会员开通");
		unifiedorder.setMch_id(mcid);
		unifiedorder.setNonce_str(noceStr);
		unifiedorder.setNotify_url(notifyurl);
		unifiedorder.setOpenid(u.getOpenid());
		unifiedorder.setOut_trade_no(payid);
		unifiedorder.setSign(sign);
		unifiedorder.setSpbill_create_ip(ip);
		unifiedorder.setTotal_fee(String.valueOf(dOrderMoney.intValue()));
		unifiedorder.setTrade_type("JSAPI");
		UnifiedOrderResult result = wx.payUnifiedOrder(unifiedorder);
		if(result.isSuccess()) {
			//生成订单
			order _order = new order();
			_order.setId(payid);
			_order.setAddtime(new Date());
			_order.setMoney(money.doubleValue());
			_order.setOrdertype(id);
			_order.setPrepay_id(result.getPrepay_id());
			_order.setStatus("1");
			_order.setTrade_type("JSAPI");
			_order.setUid(u.getOpenid());
			orderServiceImpl.add(_order);

			getReq().setAttribute("appId", appid);
			getReq().setAttribute("nonceStr", noceStr);
			getReq().setAttribute("payid", result.getPrepay_id());
			getReq().setAttribute("signType", "MD5");
			getReq().setAttribute("paySign", sign);
			getReq().setAttribute("money", money);

			reqData = new HashMap<>();
			String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
			String packages = "prepay_id="+result.getPrepay_id();
			reqData.put("appId", appid);
			reqData.put("timeStamp", timestamp);
			reqData.put("nonceStr", noceStr);
			reqData.put("package", packages);
			reqData.put("signType", "MD5");
			getReq().setAttribute("paySign", WXPayUtil.generateSignature(reqData, Configuration.getMCKey(), SignType.MD5));
			getReq().setAttribute("timeStamp", timestamp);
		}
		else {
			getReq().setAttribute("errorcode", result.getReturn_msg());
		}

		return "wechat/pay/paydetail";
	}

	public static void main(String[] args) {
		OpenPayController open = new OpenPayController();
		open.result();
	}

	/**
	 * 支付结果
	 */
	@RequestMapping("/result")
	@ResponseBody
	public void result() {
		String out_trade_no="";
		String return_code ="";
		String total_fee = "";
		try {
			InputStream inStream = getReq().getInputStream();
			ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			outSteam.close();
			inStream.close();
			String resultStr  = new String(outSteam.toByteArray(),"utf-8");
			Logger.getLogger(this.getClass()).info("支付成功的回调："+resultStr);

			Map<String, String> resultMap = WXPayUtil.xmlToMap(resultStr);
			String result_code = (String) resultMap.get("result_code");
			String is_subscribe = (String) resultMap.get("is_subscribe");
			String transaction_id = (String) resultMap.get("transaction_id");
			String sign = (String) resultMap.get("sign");
			String time_end = (String) resultMap.get("time_end");
			String bank_type = (String) resultMap.get("bank_type");

			out_trade_no = (String) resultMap.get("out_trade_no");
			return_code = (String) resultMap.get("return_code");
			total_fee = resultMap.get("total_fee");

			//通知微信.异步确认成功.必写.不然微信会一直通知后台.八次之后就认为交易失败了.
			String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code>"
					+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
			getResponse().getWriter().write(resXml);
		}
		catch (Exception e) {
			Logger.getLogger(this.getClass()).error("支付错误："+e.toString());
		}
		if(return_code.equals("SUCCESS")){
			//更新订单状态
			try {
				XHServiceImpl<xh> xHServiceImpl = (XHServiceImpl<xh>)SpringContextUtil.getApplicationContext().getBean("XHServiceImpl");
				WXUserServiceImpl<user> wxUserServiceImpl = (WXUserServiceImpl<user>)SpringContextUtil.getApplicationContext().getBean("WXUserServiceImpl");
				OrderServiceImpl<order> orderServiceImpl = (OrderServiceImpl<order>)SpringContextUtil.getApplicationContext().getBean("orderServiceImpl");
				SYSCodeServiceImpl<SYSCodeBean> sYSCodeServiceImpl = (SYSCodeServiceImpl<SYSCodeBean>)SpringContextUtil.getApplicationContext().getBean("SYSCodeServiceImpl");

				order _order = orderServiceImpl.queryById(out_trade_no);
				if(!_order.getStatus().equals("1")) return;

				BigDecimal moneyOrder = new BigDecimal(_order.getMoney());  
				BigDecimal bignum2 = new BigDecimal("100");
				BigDecimal orderMoney = moneyOrder.multiply(bignum2);
				
//				if(orderMoney.compareTo(new BigDecimal(total_fee))!=0) {
//					Logger.getLogger(this.getClass()).error("金额不对,"+orderMoney.toString()+","+total_fee);
//					return;//金额不对
//				}
				_order.setStatus("2");
				_order.setPaytime(new Date());
				orderServiceImpl.update(_order);

				//生成序号
				String strxh = String.valueOf(System.currentTimeMillis());
				xh _xh = new xh();
				_xh.setAddtime(new Date());
				_xh.setId(UUID.randomUUID().toString());
				_xh.setUid(_order.getUid());
				_xh.setXh(strxh);

				if(_order.getOrdertype().equals("6")) {
					Calendar cal = Calendar.getInstance();
					cal.add(Calendar.DATE, 5);

					_xh.setLastcount(1000000);
					_xh.setTotalcount(1000000);
					_xh.setLasttime(cal.getTime());
				}
				else if(_order.getOrdertype().equals("2")) {//尊享
					Calendar cal = Calendar.getInstance();
					cal.add(Calendar.DATE, 30);

					_xh.setLastcount(1000000);
					_xh.setTotalcount(1000000);
					_xh.setLasttime(cal.getTime());
				}
				else if(_order.getOrdertype().equals("8")) {//至尊
					Calendar cal = Calendar.getInstance();
					cal.add(Calendar.DATE, 60);
					_xh.setLastcount(1000000);
					_xh.setTotalcount(1000000);
					_xh.setLasttime(cal.getTime());
				}
				//首先判断是否已经开通
				xh temXh = xHServiceImpl.getByUserid(_order.getUid());
				Date now = new Date();
				if(temXh!=null&&now.before(temXh.getLasttime())&&temXh.getLastcount()>0) {
					temXh.setLastcount(_xh.getLastcount()+temXh.getLastcount());
					temXh.setTotalcount(_xh.getTotalcount()+temXh.getTotalcount());
					Calendar cal = Calendar.getInstance();
					cal.setTime(temXh.getLasttime());
					if(_order.getOrdertype().equals("6"))
						cal.add(Calendar.DATE, 5);
					else if(_order.getOrdertype().equals("2"))
						cal.add(Calendar.DATE, 30);
					else if(_order.getOrdertype().equals("8"))
						cal.add(Calendar.DATE, 60);
					temXh.setLasttime(cal.getTime());
					
					xHServiceImpl.updateTotalCount(temXh);
				}
				else
					xHServiceImpl.add(_xh);

				//判断是否有推荐人
				user u = wxUserServiceImpl.queryById(_order.getUid());
				if(!CommonUtil.isNullObject(u.getQr_scene_str())) {//增加推荐金额
					SYSCodeBean codebean = sYSCodeServiceImpl.queryById("005");//一级
					double money1 = Double.valueOf(codebean.getValue());
					
					user pu = wxUserServiceImpl.queryById(u.getQr_scene_str());
					Double money = _order.getMoney()*money1;
					wxUserServiceImpl.updateMoney(pu.getOpenid(), money);

					//推荐记录
					RecommendgoldServiceImpl<recommendgold> recommendgoldServiceImpl = (RecommendgoldServiceImpl<recommendgold>)SpringContextUtil.getApplicationContext().getBean("recommendgoldServiceImpl");
					recommendgold recommend = new recommendgold();
					recommend.setId(UUID.randomUUID().toString());
					recommend.setAddtime(new Date());
					recommend.setIncomeid(pu.getOpenid());
					recommend.setOrderuid(_order.getUid());
					recommend.setMoney(money);
					recommendgoldServiceImpl.add(recommend);
					
					//是否存在A
					if(!CommonUtil.isNullObject(pu.getQr_scene_str())) {
						SYSCodeBean codebean2 = sYSCodeServiceImpl.queryById("006");//二级
						user puu = wxUserServiceImpl.queryById(pu.getQr_scene_str());
						double money2 = Double.valueOf(codebean2.getValue());
						money = _order.getMoney()*money2;
						wxUserServiceImpl.updateMoney(puu.getOpenid(), money);
						
						recommend = new recommendgold();
						recommend.setId(UUID.randomUUID().toString());
						recommend.setAddtime(new Date());
						recommend.setIncomeid(puu.getOpenid());
						recommend.setOrderuid(_order.getUid());
						recommend.setMoney(money);
						recommendgoldServiceImpl.add(recommend);
					}

				}
			} catch (Exception e) {
				Logger.getLogger(this.getClass()).error("增加序号错误:"+e.toString());
				e.printStackTrace();
			}
		}else{
			//支付失败的业务逻辑
		}
	}
}
